如果今天應用程式掛掉、導致服務無法提供使用者存取,希望 k8s 可以即時將服務重新 run 起來、使服務不被中斷,這時候就要提到 k8s 中的 ReplicaSet。
當應用程式的使用者增加時,需要提升服務的高可用性 (Hign Availability, HA)、提升負載平衡,或者是為了因應服務異常中斷,需要在環境中部署多個 instances,也就是多個 pods。
在 k8s 中可以用 ReplicaSet 來對 Pods 進行管理與監控。
ReplicaSet 是監控 pod 的一個程序,確保受到管理的 pods(應用服務都是放在 pod 中) 狀態為正常運行(running)。
ReplicaSet 主要的功能:
為達成 HA 及負載平衡,在叢集中通常會部署多個 pods。透過先前在 YAML 設定檔中的 labels
屬性以及待會將提到的 selector
屬性來指定 ReplicaSet 要管理哪些 pods。
透過幫 pods 貼標籤 labels
,並在 ReplicaSet 上定義 selector
指定要管理哪些 pods。
圖片來源: https://velog.io/@gentledev10/kubernetes-replicaset
底下是一個用來建立應用程式的 pod 範例 nginx-pod.yaml
。
apiVersion: v1
kind: Pod
metadata: nginx-pod
name: nginx-pod
labels:
app: nginx-app
tier: frontend
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
底下是一個 ReplicaSet 範例 nginx-rs.yaml
,假設希望在叢集中維持執行 3 個 pods。
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-rs
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
# 若是 pod 掛掉時,ReplicaSet 會按照以下內容來建立新的 pod
metadata:
name: nginx-pod
labels:
app: nginx-app
tier: frontend
spec:
containers:
- name: nginx-container
image: nginx
ports:
- containerPort: 80
如同 pod 的定義一樣,有 apiVersion
、kind
、metadata
和 spec
屬性,不同的是在 spec
定義:
replicas
:需要幾個 replica,這邊希望在叢集中跑三個 pods。selector
:定義要管理的 labels
有哪些,在 matchLabels
下填上標籤 app
其值為 nginx-app
,表示要連結至有此標籤的所有 pods。可以將不是由設定檔建立的 pod 也納入 replicaSet 的管理。template
:pod 的詳細內容,其實就是把建立 pod 的設定檔底下的 metadata
及 spec
兩個屬性的內容原封不動搬過來。status
:實際由 k8s 於執行時自動產生與更新,在定義時可不寫。執行 nginx-rs.yaml
。
kubectl create -f nginx-rs.yaml
replicaset.apps/nginx-rs created
查看建立的 pods。
kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-rs-dpghz 1/1 Running 0 106s
nginx-rs-nrw5r 1/1 Running 0 106s
nginx-rs-qpt2v 1/1 Running 0 106s
也可以用 label
篩選 pods,先建立一個沒有 label 的 pod。
kubectl run nginx --image=nginx
kubectl get po
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 37s
nginx-rs-dpghz 1/1 Running 0 3m33s
nginx-rs-nrw5r 1/1 Running 0 3m33s
nginx-rs-qpt2v 1/1 Running 0 3m33s
篩選 label
為 tier=frontend
的 pod。
kubectl get po -l tier=frontend
NAME READY STATUS RESTARTS AGE
nginx-rs-dpghz 1/1 Running 0 4m43s
nginx-rs-nrw5r 1/1 Running 0 4m43s
nginx-rs-qpt2v 1/1 Running 0 4m43s
加上 -o wide
可以看到 ReplicaSet 的 selector
為 app=nginx-app
。
kubectl get replicaset nginx-rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
nginx-rs 3 3 3 6m13s nginx-container nginx app=nginx-app
刪掉 nginx
pod。
kubectl delete po nginx
pod "nginx" deleted
查看該 ReplicaSet 的詳細資料。
kubectl describe replicaset nginx-rs
Name: nginx-rs
Namespace: default
Selector: app=nginx-app
Labels: <none>
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=nginx-app
tier=frontend
Containers:
nginx-container:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 7m22s replicaset-controller Created pod: nginx-rs-nrw5r
Normal SuccessfulCreate 7m22s replicaset-controller Created pod: nginx-rs-dpghz
Normal SuccessfulCreate 7m22s replicaset-controller Created pod: nginx-rs-qpt2v
觀察 selector
、labels
、Replicas
、Pods Status
和底下的 Events
(建立 pod 的事件紀錄)。
若想要修改 ReplicaSet,例如把其中的 replicas 修改為其他數量,有三種修改方式:
nginx-rs.yaml
內的內容kubectl scale
指令kubectl edit
指令先來看第 1 種直接修改 nginx-rs.yaml
。
kubectl replace -f nginx-rs.yaml
replicaset.apps/nginx-rs replaced
修改其中的 replicas
為 2。
vi nginx-rs.yaml
查看 ReplicaSet。
kubectl get rs nginx-rs
NAME DESIRED CURRENT READY AGE
nginx-rs 2 2 2 6m4s
查看 pods running 變為 2 個。
kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-rs-jcq5h 1/1 Running 0 6m42s
nginx-rs-whmw6 1/1 Running 0 6m42s
第 2 種使用 scale
設定 replicas
為 6。
kubectl scale replicaset nginx-rs --replicas=6
replicaset.apps/nginx-rs scaled
查看當前 ReplicaSet。
kubectl get rs nginx-rs
NAME DESIRED CURRENT READY AGE
nginx-rs 6 6 6 18m
查看 pods running 變為 6 個。
kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-rs-6825z 1/1 Running 0 2m4s 10.244.0.15 minikube <none> <none>
nginx-rs-dpghz 1/1 Running 0 19m 10.244.0.11 minikube <none> <none>
nginx-rs-g94bm 1/1 Running 0 2m4s 10.244.0.13 minikube <none> <none>
nginx-rs-l2zp5 1/1 Running 0 2m4s 10.244.0.14 minikube <none> <none>
nginx-rs-nrw5r 1/1 Running 0 19m 10.244.0.10 minikube <none> <none>
nginx-rs-qpt2v 1/1 Running 0 19m 10.244.0.9 minikube <none> <none>
第 3 種是使用 edit
,把 replicas
改回 3。
# k8s 會提供一個暫時的 file 可以修改,若儲存後則 apply 這個版本的 replicaset
kubectl edit replicaset nginx-rs
replicaset.apps/nginx-rs edited
查看當前 ReplicaSet 跟 pods,scale down 後變為 3。
kubectl get rs,po
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-rs 3 3 3 27m
NAME READY STATUS RESTARTS AGE
pod/nginx-rs-dpghz 1/1 Running 0 27m
pod/nginx-rs-nrw5r 1/1 Running 0 27m
pod/nginx-rs-qpt2v 1/1 Running 0 27m
注意:使用第 2 種(
kubectl scale
)與第 3 種(kubectl edit
)方式並不會自動修改nginx-rs.yaml
設定檔裡的內容,下次再執行時replicas
依然是原本的 3。
同時刪除所有在設定檔中建立與管理的 pods,也就是 labels
有對應到的 pods。
kubectl delete replicaset nginx-rs
replicaset.apps "nginx-rs" deleted
查看 ReplicaSet。
kubectl get replicaset
No resources found in default namespace.
status
屬性是由 k8s 自動產生與變動的,在執行 kubectl create -f nginx-rs.yaml
或異動 ReplicaSet 後,k8s 會去 etcd 取得叢集中 status
的資料,並比對當前叢集的狀態、設定檔中的狀態有沒有一致。
例如修改 nginx-rs.yaml
的 replicas
為 2。
vi nginx-rs.yaml
kubectl replace -f nginx-rs.yaml
replicaset.apps/nginx-rs replaced
可以透過 kubectl edit
來觀察。
kubectl edit replicaset nginx-rs
# 省略部分 ...
spec:
replicas: 2
selector:
matchLabels:
app: nginx-app
template:
metadata:
creationTimestamp: null
labels:
app: nginx-app
tier: frontend
name: nginx-pod
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx-container
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
fullyLabeledReplicas: 2
observedGeneration: 2
readyReplicas: 2
replicas: 2
如上可以看到 status
屬性。